package org.sun.online.service.verification.application.impl;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.sun.online.internal.common.dto.verification.code.VerifyCodeRequest;
import org.sun.online.internal.common.dto.verification.code.VerifyCodeResponse;
import org.sun.online.internal.common.enums.IdentityEnum;
import org.sun.online.service.verification.application.VerificationApplicationService;
import org.sun.online.service.verification.types.Identity;
import org.sun.online.service.verification.types.PhoneNumber;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author sunhongmin
 * @date 2022/6/4 16:28
 * @description
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class VerificationApplicationServiceImpl implements VerificationApplicationService {

    private final RedisTemplate<String, String> redisTemplate;

    @Override
    public VerifyCodeResponse verifyCodeGenerate(Identity identity, PhoneNumber phoneNumber) {
        // 校验
        IdentityEnum.checkIdentityLegal(identity.getIdentity());
        // 获取枚举实例
        IdentityEnum instance = IdentityEnum.getInstance(identity.getIdentity());
        // 获得redis key 前缀
        String redisKeyPrefix = instance.getRedisKeyPrefix();
        // [a,b] = Math.random() * (b - a + 1) + a
        String randomCode = String.valueOf((int) (Math.random() * 900000 + 100000));
        // redis key
        String phoneNumberValue = phoneNumber.getPhoneNumber();
        //存redis，2分钟过期
        BoundValueOperations<String, String> codeRedis = redisTemplate.boundValueOps(redisKeyPrefix + phoneNumberValue);
        codeRedis.set(randomCode, 2, TimeUnit.MINUTES);
        // redis 控制限流 存在有效期验证码，不能重复发送
        // 错误验证码控制 1分钟3次 五分钟之内不能登录 1小时发了10次则限制24小时不能登录
        return new VerifyCodeResponse(randomCode);
    }

    @Override
    public boolean verifyCode(VerifyCodeRequest verifyCodeRequest) {
        IdentityEnum instance = IdentityEnum.getInstance(verifyCodeRequest.getIdentity());
        String redisKeyPrefix = instance.getRedisKeyPrefix();
        BoundValueOperations<String, String> codeRedis = redisTemplate.boundValueOps(redisKeyPrefix + verifyCodeRequest.getPhoneNumber());
        String codeFormRedis = codeRedis.get();
        if (StringUtils.isNotBlank(codeFormRedis)) {
            if (Objects.equals(codeFormRedis, verifyCodeRequest.getCode())) {
                return true;
            }
        }

        log.error(">>> verifyCode error request:{},codeFormRedis:{},keyExpire:{}", verifyCodeRequest, codeFormRedis, codeRedis.getExpire());
        return false;
    }
}
